home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
comm
/
mpmod160.zip
/
SOURCE.ZIP
/
Z-TX.C
< prev
Wrap
C/C++ Source or Header
|
1994-01-01
|
20KB
|
686 lines
/*---------------------------------------------------------------------------*/
/* The send part of the Zmodem protocol. */
/* */
/* (C) Copyright M. Jose, 1990 -> */
/* See MPMODEM.DOC for more details about the usage of this source in your */
/* programs. */
/* Written by Mark Jose, Oct-Nov, 1990. */
/*---------------------------------------------------------------------------*/
[...]
#include "compress.h"
[...]
/*
Private routines
*/
[...]
static int pascal SendData(register BYTE *, register int, int);
/*
If you don't have a separate routine to handle crc-16 transfers, then you
will have to create one.
Some people implement Zmodem without the ability to run it in CRC-16 mode
because it will always default to the safer CRC-32 mode. This is fine, but
when you want to use it over quite secure lines, CRC-16 is quite adequate.
*/
static void pascal SendData16(register BYTE *, register int, int);
static void pascal SendData32(register BYTE *, register int, int);
[...]
/*
SEND BINARY HEADER
Send ZMODEM binary header hdr of type type
*/
static int pascal SendBinaryHeader(int type, BYTE *hdr)
{
static int n;
BufferByte(ZPAD);
BufferByte(ZDLE);
/*
TxType is the variable that determines the type of transfer. This variable
can change during a file transfer (for hex headers) and must be re-instated
here or else we will have a mix up in the type of transfer mode being used.
TxMaster is determined in the negotiation phase of the transfer. For a
better understanding of its values see that routine (called GetReceiver().)
*/
switch(TxType = TxMaster) {
/*
If the TxType is 4 or 3 then the transmission will perhaps involve
compressed data. We must signal the receiver that this is our intention.
We do this by sending either a ZBINC or ZBINC32 frame header.
*/
case 4:
SendBinaryHeader16(hdr, type, ZBINC);
break;
case 3:
SendBinaryHeader32(hdr, type, ZBINC32);
break;
/* --- */
case 2:
default:
return -1;
case 1:
SendBinaryHeader32(hdr, type, ZBIN32);
break;
case 0:
SendBinaryHeader16(hdr, type, ZBIN);
break;
}
n = UnbufferBytes();
return n;
}
/*
Send binary header with standard CRC-16
*/
static void pascal SendBinaryHeader16(BYTE *hdr, int type, int flavour)
{
static unsigned short crc;
register int n;
BufferByte(flavour);
ZS_SendByte(type);
crc = Z_UpdateCRC(type, 0);
for (n = 4; --n >= 0;) {
ZS_SendByte(*hdr);
crc = Z_UpdateCRC(((unsigned short)(*hdr++ & 0xFF)), crc);
}
ZS_SendByte((BYTE ) (crc >> 8));
ZS_SendByte((BYTE ) crc);
}
/*
Send binary header with CRC-32
*/
static void pascal SendBinaryHeader32(BYTE *hdr, int type, int flavour)
{
register int n;
static ULONG crc;
BufferByte(flavour);
ZS_SendByte(type);
crc = Z_UpdateCRC32(type, 0xFFFFFFFFL);
for (n = 4; --n >= 0; ) {
ZS_SendByte(*hdr);
crc = Z_UpdateCRC32((0xFF & *hdr++), crc);
}
crc = ~crc;
for (n = 4; --n >= 0;) {
ZS_SendByte((int )crc);
crc >>= 8;
}
}
/*
Send binary data in buf (or Compbuff if compressed)
*/
static int pascal SendData(register BYTE *buf, register int length, int frameend)
{
static int n;
static int comp_lgh;
/*
This routine determines which routine we should branch off to depending upon
the type of CRC checking that was negotiated at startup.
If the transmission allows for compressed data, then the TxType will be
either 4 or 3. In which case, we will attempt to compress the data into a
block smaller than the "length" passed to us. If this is not possible then
we will send the packet normally.
What we do below is determine if the compressed length is smaller than the
length of the uncompressed block. If it is, we flag the transmission as a
"Compressed" transmission and increment the frame-end by 8. For example:
ZCRCE => 'h' => 104 + 8 = 112 => 'p' => ZCRCE_C
ZCRCG => 'i' => 105 + 8 = 113 => 'q' => ZCRCG_C
ZCRCQ => 'j' => 106 + 8 = 114 => 'r' => ZCRCQ_C
ZCRCW => 'k' => 107 + 8 = 115 => 's' => ZCRCW_C
This then makes the current frame a compressed frame as well as allowing
us to keep its original status.
*/
if (TxType == 3 || TxType == 4) {
comp_lgh = Compress(buf, CompBuff, length);
if (comp_lgh < length) {
Compressed = 1;
frameend += 8; /* Bumps up the frame end to indicate compression */
} else {
Compressed = 0;
comp_lgh = length;
}
}
switch(TxType) {
/*
Right, now we process the compressed or uncompressed buffer. If the data
was able to be compressed into less space than the uncompressed buffer, then
the "Compressed" flag would have been set to 1 above. In this case, the data
we need to send is contained in "CompBuff". If the data could not be
compressed then "Compressed" would be set to 0 and we will send the data from
the "buf" buffer. Simple, hey?!
*/
case 4:
SendData16(Compressed ? CompBuff : buf, comp_lgh, frameend);
break;
case 3:
SendData32(Compressed ? CompBuff : buf, comp_lgh, frameend);
break;
/* --- */
case 2:
default:
return ZERROR;
case 1:
SendData32(buf, length, frameend);
break;
default:
SendData16(buf, length, frameend);
break;
}
n = UnbufferBytes();
[...]
return n;
}
/*
SEND DATA with 16 bit CRC (and compression if necessary).
*/
static void pascal SendData16(register BYTE *buf, register int length, int frameend)
{
static WORD crc;
crc = 0;
for (;--length >= 0;) {
SendByte(*buf);
crc = UpdateCRC(((WORD )(0xFF & *buf++)), crc);
}
BufferByte(ZDLE);
BufferByte(frameend);
crc = UpdateCRC(frameend, crc);
SendByte(crc >> 8);
SendByte(crc);
}
/*
SEND DATA with 32 bit CRC (and compressed if necessary)
*/
static void pascal SendData32(register BYTE *buf, register int length, int frameend)
{
static int c;
static ULONG crc;
crc = 0xFFFFFFFFL;
for (;--length >= 0;) {
c = *buf & 0xFF;
if ((c & 0140)) {
BufferByte((lastsent = c));
} else {
SendByte(c);
}
crc = UpdateCRC32(( (WORD )(*buf++) ), crc);
}
BufferByte(ZDLE);
BufferByte(frameend);
crc = UpdateCRC32(frameend, crc);
crc = ~crc;
for (length = 4; --length >= 0;) {
SendByte((int )crc);
crc >>= 8;
}
}
/*
Send character c with ZMODEM escape sequence encoding.
Don't encode special characters if FAST mode is being used.
*/
static void pascal SendByte(BYTE ch)
{
/*
Here is the core routine for sending data to the remote without any form of
escape encoding other than for the Zmodem required ZDLE. This means the
transmission can be faster if (for example) you have an 8 bit connect and
no need for software transmission control.
*/
if (UsingFast) {
if ((ch & 0xFF) == ZDLE) {
BufferByte(ZDLE);
lastsent = (ZDLE ^ 0x40);
} else
lastsent = ch & 0xFF;
BufferByte(lastsent);
return;
}
if ((ch & 0x60)) {
lastsent = ch;
} else {
switch (ch & 0x7F) {
case ZDLE:
case 16:
case 17:
case 19:
BufferByte(ZDLE);
lastsent = (ch ^ 0x40);
break;
case 13:
if (ZCtlEsc && ((lastsent & 0x7f) != '@'))
lastsent = ch;
else {
BufferByte(ZDLE);
lastsent = (ch ^ 0x40);